use std::collections::HashMap;
use std::fs;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
/**
 * 读取并解析YAML文件，将其内容转换为HashMap。
 *
 * 此函数打开指定路径的YAML文件，逐行读取并解析其内容。
 * 它使用缩进来确定键的层次结构，并将键值对插入到HashMap中。
 *
 * 参数:
 * - file_path: &str - YAML文件的路径。
 *
 * 返回:
 * - Result<HashMap<String,String>, Box<dyn std::error::Error>>:
 *   成功时返回包含解析键值对的HashMap，失败时返回错误。
 */
pub fn _read_yaml(file_path: &str) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
    // 读取文件内容
    let contents = std::fs::read_to_string(file_path).expect("Error reading file");
    // 初始化配置HashMap
    let mut config = HashMap::new();
    // 初始化键名栈，用于跟踪当前的键层次结构
    let mut key_stack = Vec::new();
    // 遍历文件的每一行
    for line in contents.lines() {
        // 移除行两端的空白字符
        let line = line.trim();
        // 忽略空行或注释行
        if line.is_empty() || line.starts_with('#') {
            continue;
        }
        // 计算当前行的缩进级别
        let indent_level = line.chars().take_while(|c| *c == ' ').count();
        // 移除行首的缩进
        let trimmed_line = line.trim();
        // 根据缩进级别调整键名栈
        while key_stack.len() > indent_level {
            key_stack.pop();
        }
        // 尝试拆分键值对
        if let Some((key, value)) = trimmed_line.split_once(":") {
            // 移除键和值的空白字符
            let key = key.trim();
            let value = value.trim().to_string();
            // 如果值为空，则将键添加到键名栈中
            if value.is_empty() {
                key_stack.push(key)
            } else {
                // 构建完整的键名，并将其与值插入到配置HashMap中
                let full_key = key_stack
                    .iter()
                    .chain([&key])
                    .cloned()
                    .collect::<Vec<_>>()
                    .join(".");
                config.insert(full_key, value);
            }
        }
    }
    // 返回解析后的配置
    Ok(config)
}

// 手动实现的百分号编码解码函数
// 解码百分号编码的字符串
// 输入参数: &str 类型的百分号编码字符串
// 返回值: 解码后的字符串
fn decode_percent_encoded(input: &str) -> String {
    // 创建一个空的向量，用于存储解码后的字节
    let mut decoded_bytes = Vec::new();
    // 创建一个字符迭代器，用于遍历输入字符串
    let mut chars = input.chars();

    // 遍历输入字符串的每个字符
    while let Some(ch) = chars.next() {
        // 如果当前字符是百分号，尝试解码接下来的两个字符
        if ch == '%' {
            // 获取接下来的两个字符，如果存在
            if let (Some(high), Some(low)) = (chars.next(), chars.next()) {
                // 将这两个字符组合成一个十六进制字符串
                let hex = format!("{}{}", high, low);
                // 尝试将十六进制字符串转换为一个u8字节
                if let Ok(byte) = u8::from_str_radix(&hex, 16) {
                    // 将转换成功的字节添加到向量中
                    decoded_bytes.push(byte);
                }
            }
        } else {
            // 如果当前字符不是百分号，直接将其添加到向量中
            decoded_bytes.push(ch as u8);
        }
    }

    // 尝试将存储解码后字节的向量转换为一个字符串
    // 如果转换失败，抛出一个panic，表明输入字符串包含了无效的UTF-8字符
    String::from_utf8(decoded_bytes).expect("Invalid UTF-8")
}

fn parse_request_line(req: &str) -> (&str, &str) {
    let mut lines = req.lines();
    let first_line = lines.next().unwrap_or("");
    let parts: Vec<&str> = first_line.split_whitespace().collect();
    if parts.len() >= 2 {
        (parts[0], parts[1])
    } else {
        ("", "")
    }
}
fn parse_query_params(url: &str) -> HashMap<String, String> {
    let mut query_params = HashMap::new();
    if let Some(query_string) = url.split('?').nth(1) {
        for param in query_string.split('&') {
            let mut key_value = param.splitn(2, '=');
            if let Some(key) = key_value.next() {
                if let Some(value) = key_value.next() {
                    let decoded_key = decode_percent_encoded(key);
                    let decoded_value = decode_percent_encoded(value);
                    query_params.insert(decoded_key, decoded_value);
                }
            }
        }
    }
    query_params
}
fn _read_file(file_path: &str, output_file_path: &str, search_str: &str) {
    let contents = fs::read_to_string(file_path).expect("Something went wrong reading the file");
    //统计指定内容出现的次数
    let _count = contents.matches(search_str).count();
    //将指定内容出现的哪一行保存到文本中
    let mut out_file = fs::File::create(output_file_path).expect("Failed to create file");
    for (i, line) in contents.lines().enumerate() {
        if line.contains(search_str) {
            writeln!(out_file, "第{}行：{}", i + 1, line).expect("Failed to write to file");
        }
    }
}

pub(crate) struct WebServer {
    port: String,
    get_routes: HashMap<String, fn(&mut std::net::TcpStream, &mut Self)>,
    pub query_params: HashMap<String, String>,
}
impl WebServer {
    pub(crate) fn new(port: &str) -> WebServer {
        WebServer {
            port: port.to_string(),
            get_routes: HashMap::new(),
            query_params: HashMap::new(),
        }
    }
    pub(crate) fn listen(&mut self) {
        let address = format!("127.0.0.1:{}", self.port);
        let listener = TcpListener::bind(&address).expect("Could not bind to address");

        println!("Server listening on http://{}", address);

        for stream in listener.incoming() {
            match stream {
                Ok(mut stream) => {
                    let mut buffer = [0; 512];
                    stream
                        .read(&mut buffer)
                        .expect("Failed to read from stream");
                    let request = String::from_utf8(buffer.to_vec()).expect("Invalid UTF-8");
                    let (method, path) = parse_request_line(&request);
                    let query_params = parse_query_params(path);
                    let ip = stream.peer_addr().unwrap().ip().to_string();
                    self.log_request(&ip, method, path);
                    self.query_params = query_params;
                    if method == "GET" {
                        if let Some(handler) =
                            self.get_routes.get(path.split('?').next().unwrap_or(""))
                        {
                            handler(&mut stream, self);
                        } else {
                            let response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nPage not found.";
                            stream
                                .write_all(response.as_bytes())
                                .expect("Failed to write response");
                        }
                    } else {
                        let response = "HTTP/1.1 405 Method Not Allowed\r\n\r\n";
                        stream
                            .write_all(response.as_bytes())
                            .expect("Failed to write response");
                    }
                }
                Err(e) => {
                    eprintln!("Connection failed: {}", e);
                }
            }
        }
    }
    // 注册 GET 路由
    pub(crate) fn get(&mut self, path: &str, handler: fn(&mut std::net::TcpStream, &mut Self)) {
        self.get_routes.insert(path.to_string(), handler);
    }

    fn _post() {}
    fn log_request(&self, ip: &str, method: &str, path: &str) {
        // ANSI 转义码
        let blue = "\x1b[34m";
        let green = "\x1b[32m";
        let yellow = "\x1b[33m";
        let reset = "\x1b[0m";

        // 记录请求
        println!(
            "[{}{}{}]: {}{}{} {}{}{}",
            blue, ip, reset, green, method, reset, yellow, path, reset
        );
    }
    pub(crate) fn hash_map_to_json(&self, map: &HashMap<String, String>) -> String {
        let mut json_string = String::from("{");

        // 迭代键值对，将它们格式化为 JSON 样式
        for (i, (key, value)) in map.iter().enumerate() {
            // 添加键值对并转义字符串内容
            json_string.push_str(&format!("\"{}\": \"{}\"", key, value));

            // 如果不是最后一个键值对，则添加逗号
            if i < map.len() - 1 {
                json_string.push_str(", ");
            }
        }

        json_string.push('}');
        json_string
    }
    pub fn json(&self, stream: &mut TcpStream, data: HashMap<String, String>) {
        let json = self.hash_map_to_json(&data);
        let response = format!(
            "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{}",
            json.len(),
            json
        );
        stream.write_all(response.as_bytes()).unwrap();
    }
    pub(crate) fn success_json(&self, stream: &mut TcpStream, data: &HashMap<String, String>) {
        let mut res = HashMap::new();
        res.insert("message".to_string(), "success".to_string());
        res.insert("status".to_string(), "200".to_string());
        res.insert("data".to_string(), self.hash_map_to_json(&data));
        self.json(stream, res);
    }
    #[allow(dead_code)]
    pub(crate) fn error(&self, stream: &mut TcpStream, message: &str) {
        let mut res = HashMap::new();
        res.insert("message".to_string(), message.to_string());
        res.insert("status".to_string(), "500".to_string());
        self.json(stream, res);
    }
    #[allow(dead_code)]
    pub(crate) fn success(&self, stream: &mut TcpStream, data: &str) {
        let mut res = HashMap::new();
        res.insert("message".to_string(), "success".to_string());
        res.insert("status".to_string(), "200".to_string());
        res.insert("data".to_string(), data.to_string());
        self.json(stream, res);
    }
}
